package com.googlecode.contests_repo.core.model;

import java.io.File;
import java.io.FileFilter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import org.codehaus.jackson.map.ObjectMapper;

import com.googlecode.contests_repo.core.config.ConfigurationManager;

/**
 * Manages Resources in the file system. Holds business logic for Resources
 * operations.
 * 
 * @author Svetla Marinova, M23322
 */
public class ResourcesUtils {
	private static final String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
	private static final String TIMEZONE_STRING = "Zulu";

	private static List<Resource> fetch(File homeDir) {
		List<Resource> result = new ArrayList<Resource>();
		File[] listFiles = homeDir.listFiles();
		for (File file : listFiles) {
			if (file.isDirectory() && !file.getName().startsWith("_")
					&& !file.getName().startsWith("souls")) {
				Resource resource = getJSON(file);
				result.add(resource);
			}
		}
		return result;
	}

	/**
	 * Fetch resource from directory
	 * 
	 * @param <T>
	 * @param homeDir
	 * @return list of resources
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> fetchResources(File homeDir) {
		List<Resource> resources = fetch(homeDir);
		List<T> series = new ArrayList<T>(resources.size());
		for (Resource resource : resources) {
			series.add((T) resource);
		}
		return series;
	}

	/**
	 * returns the resource object associated with json for the resource
	 * contained in a given directory
	 * 
	 * @param <T>
	 * @param directory
	 * @return the resource object associated with json for the resource
	 *         contained in a given directory
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getJSON(File directory) {
		File[] listFiles = directory.listFiles(new FileFilter() {

			public boolean accept(File pathname) {
				if (!pathname.isDirectory()
						&& !pathname.getName().startsWith(
								ConfigurationManager.getInstance()
										.getSecurityFileName())
						&& pathname.getName().endsWith(".json")) {
					return true;
				}
				return false;
			}
		});
		Resource resource = null;
		ObjectMapper mapper = new ObjectMapper();
		try {
			Class<? extends Resource> z = null;
			File resourceFile = listFiles[0];
			if (resourceFile.getName().startsWith("contest")) {
				z = Contest.class;
			} else if (resourceFile.getName().startsWith("problem")) {
				z = Problem.class;
			} else if (resourceFile.getName().startsWith("series")) {
				z = Series.class;
			}
			resource = mapper.readValue(resourceFile, z);

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return (T) resource;
	}

	/**
	 * Checks if a resource has started
	 * 
	 * @param dateString
	 * @return true if the resource has started, false otherwise
	 */
	public static boolean hasStarted(String dateString) {
		Date currentTime = new Date();
		if (currentTime.getTime() - extractDate(dateString).getTime() >= 0) {
			return true;
		}
		return false;
	}

	/**
	 * Checks if a resource has ended
	 * 
	 * @param dateString
	 * @param duration
	 * @return true if the resource has ended, false otherwise
	 */
	public static boolean hasEnded(String dateString, int duration) {
		Date currentTime = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
				DateFormat.LONG);
		dateFormat.setTimeZone(TimeZone.getTimeZone(TIMEZONE_STRING));
		if (currentTime.getTime()
				- (extractDate(dateString).getTime() + duration * 60) >= 0) {
			return true;
		}
		return false;
	}

	private static Date extractDate(String dateString) {
		DateFormat dateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
		dateFormat.setTimeZone(TimeZone.getTimeZone(TIMEZONE_STRING));
		Date extractedDate = null;
		try {
			extractedDate = dateFormat.parse(dateString);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return extractedDate;
	}
}